<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">

<head>
    <!-- Book generated using mdBook -->
    <meta charset="UTF-8">
    <title>扑克 - exercisms.io 快速练习</title>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
    <meta name="description" content="exercisms 的练习，网页版.">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="theme-color" content="#ffffff" />

    <link rel="shortcut icon" href="../favicon.png">
    <link rel="stylesheet" href="../css/variables.css">
    <link rel="stylesheet" href="../css/general.css">
    <link rel="stylesheet" href="../css/chrome.css">
    <link rel="stylesheet" href="../css/print.css" media="print">

    <!-- Fonts -->
    <link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
    <link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800"
        rel="stylesheet" type="text/css">
    <link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">

    <!-- Highlight.js Stylesheets -->
    <link rel="stylesheet" href="../highlight.css">
    <link rel="stylesheet" href="../tomorrow-night.css">
    <link rel="stylesheet" href="../ayu-highlight.css">

    <!-- Custom theme stylesheets -->
    
    <link rel="stylesheet" href="../theme/custom.css">
    

    
</head>

<body class="light">
    <!-- Provide site root to javascript -->
    <script type="text/javascript">var path_to_root = "../";</script>

    <!-- Work around some values being stored in localStorage wrapped in quotes -->
    <script type="text/javascript">
        try {
            var theme = localStorage.getItem('mdbook-theme');
            var sidebar = localStorage.getItem('mdbook-sidebar');

            if (theme.startsWith('"') && theme.endsWith('"')) {
                localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
            }

            if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
            }
        } catch (e) { }
    </script>

    <!-- Set the theme before any content is loaded, prevents flash -->
    <script type="text/javascript">
        var theme;
        try { theme = localStorage.getItem('mdbook-theme'); } catch (e) { }
        if (theme === null || theme === undefined) { theme = 'light'; }
        document.body.className = theme;
        document.querySelector('html').className = theme + ' js';
    </script>

    <!-- Hide / unhide sidebar before it is displayed -->
    <script type="text/javascript">
        var html = document.querySelector('html');
        var sidebar = 'hidden';
        if (document.body.clientWidth >= 1080) {
            try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch (e) { }
            sidebar = sidebar || 'visible';
        }
        html.classList.remove('sidebar-visible');
        html.classList.add("sidebar-" + sidebar);
    </script>

    <nav id="sidebar" class="sidebar" aria-label="Table of contents">
        <ol class="chapter"><li><a href="../index.html"><strong aria-hidden="true">1.</strong> 超过 88 道练习，任点</a></li><li><a href="../low.html"><strong aria-hidden="true">2.</strong> 易</a></li><li><ol class="section"><li><a href="../hello-world/README.zh.html"><strong aria-hidden="true">2.1.</strong> hello world</a></li><li><a href="../gigasecond/README.zh.html"><strong aria-hidden="true">2.2.</strong> 千兆秒 &gt;&lt; Gigasecond)</a></li><li><a href="../leap/README.zh.html"><strong aria-hidden="true">2.3.</strong> 闰年 &gt;&lt; Leap</a></li><li><a href="../raindrops/README.zh.html"><strong aria-hidden="true">2.4.</strong> 雨滴声 &gt;&lt; Raindrops</a></li><li><a href="../reverse-string/README.zh.html"><strong aria-hidden="true">2.5.</strong> 反转字符串 &gt;&lt; Reverse String</a></li><li><a href="../nth-prime/README.zh.html"><strong aria-hidden="true">2.6.</strong> 第 n 个素数 &gt;&lt; Nth Prime</a></li><li><a href="../bob/README.zh.html"><strong aria-hidden="true">2.7.</strong> 迟钝孩子 &gt;&lt; Bob</a></li><li><a href="../beer-song/README.zh.html"><strong aria-hidden="true">2.8.</strong> 啤酒之歌 &gt;&lt; Beer Song</a></li><li><a href="../proverb/README.zh.html"><strong aria-hidden="true">2.9.</strong> 谚语串烧 &gt;&lt; Proverb</a></li><li><a href="../difference-of-squares/README.zh.html"><strong aria-hidden="true">2.10.</strong> 平方差 &gt;&lt; Difference Of Squares</a></li><li><a href="../sum-of-multiples/README.zh.html"><strong aria-hidden="true">2.11.</strong> 倍数之和 &gt;&lt; Sum Of Multiples</a></li><li><a href="../grains/README.zh.html"><strong aria-hidden="true">2.12.</strong> 谷物 &gt;&lt; Grains</a></li><li><a href="../pythagorean-triplet/README.zh.html"><strong aria-hidden="true">2.13.</strong> 勾股数 &gt;&lt; Pythagorean Triplet</a></li><li><a href="../prime-factors/README.zh.html"><strong aria-hidden="true">2.14.</strong> 素数因子 &gt;&lt; Prime Factors</a></li><li><a href="../series/README.zh.html"><strong aria-hidden="true">2.15.</strong> 子串 &gt;&lt; Series</a></li><li><a href="../armstrong-numbers/README.zh.html"><strong aria-hidden="true">2.16.</strong> 水仙花数 &gt;&lt; Armstrong Numbers</a></li><li><a href="../collatz-conjecture/README.zh.html"><strong aria-hidden="true">2.17.</strong> 3n+1 猜想 &gt;&lt; Collatz Conjecture</a></li><li><a href="../diffie-hellman/README.zh.html"><strong aria-hidden="true">2.18.</strong> 迪菲-赫尔曼密钥交换 &gt;&lt; Diffie Hellman</a></li></ol></li><li><a href="../medium.html"><strong aria-hidden="true">3.</strong> 中等</a></li><li><ol class="section"><li><a href="../saddle-points/README.zh.html"><strong aria-hidden="true">3.1.</strong> 鞍点 &gt;&lt; Saddle Points</a></li><li><a href="../isogram/README.zh.html"><strong aria-hidden="true">3.2.</strong> 等值线 &gt;&lt; Isogram</a></li><li><a href="../say/README.zh.html"><strong aria-hidden="true">3.3.</strong> 英文说数字 &gt;&lt; Say</a></li><li><a href="../run-length-encoding/README.zh.html"><strong aria-hidden="true">3.4.</strong> 游程编码 &gt;&lt; Run Length Encoding</a></li><li><a href="../isbn-verifier/README.zh.html"><strong aria-hidden="true">3.5.</strong> 图书编号 &gt;&lt; ISBN Verifier</a></li><li><a href="../perfect-numbers/README.zh.html"><strong aria-hidden="true">3.6.</strong> 数字也能分类 &gt;&lt; Perfect Numbers</a></li><li><a href="../clock/README.zh.html"><strong aria-hidden="true">3.7.</strong> 时钟 &gt;&lt; Clock</a></li><li><a href="../dot-dsl/README.zh.html"><strong aria-hidden="true">3.8.</strong> DOT DSL</a></li><li><a href="../hamming/README.zh.html"><strong aria-hidden="true">3.9.</strong> 汉明距离 &gt;&lt; Hamming</a></li><li><a href="../simple-linked-list/README.zh.html"><strong aria-hidden="true">3.10.</strong> 简单链表 &gt;&lt; Simple Linked List</a></li><li><a href="../pascals-triangle/README.zh.html"><strong aria-hidden="true">3.11.</strong> 杨辉三角形 &gt;&lt; Pascal's Triangle</a></li><li><a href="../scrabble-score/README.zh.html"><strong aria-hidden="true">3.12.</strong> 字母的分数游戏 &gt;&lt; Scrabble Score</a></li><li><a href="../pangram/README.zh.html"><strong aria-hidden="true">3.13.</strong> 全字母句 &gt;&lt; Pangram</a></li><li><a href="../paasio/README.zh.html"><strong aria-hidden="true">3.14.</strong> PaaS-IO-报告 &gt;&lt; Paasio</a></li><li><a href="../nucleotide-count/README.zh.html"><strong aria-hidden="true">3.15.</strong> 核苷酸计数 &gt;&lt; Nucleotide Count</a></li><li><a href="../luhn/README.zh.html"><strong aria-hidden="true">3.16.</strong> 模 10 算法 &gt;&lt; Luhn</a></li><li><a href="../largest-series-product/README.zh.html"><strong aria-hidden="true">3.17.</strong> 最大数字子串乘积 &gt;&lt; Largest Series Product</a></li><li><a href="../word-count/README.zh.html"><strong aria-hidden="true">3.18.</strong> 单词计数 &gt;&lt; Word Count</a></li><li><a href="../atbash-cipher/README.zh.html"><strong aria-hidden="true">3.19.</strong> Atbash 加密 &gt;&lt; Atbash Cipher</a></li><li><a href="../crypto-square/README.zh.html"><strong aria-hidden="true">3.20.</strong> 密码矩形 &gt;&lt; Crypto Square</a></li><li><a href="../rotational-cipher/README.zh.html"><strong aria-hidden="true">3.21.</strong> 旋转密码 &gt;&lt; Rotational Cipher</a></li><li><a href="../simple-cipher/README.zh.html"><strong aria-hidden="true">3.22.</strong> 简单加密 &gt;&lt; Simple Cipher</a></li><li><a href="../rail-fence-cipher/README.zh.html"><strong aria-hidden="true">3.23.</strong> 栅栏密码 &gt;&lt; Rail Fence Cipher</a></li><li><a href="../etl/README.zh.html"><strong aria-hidden="true">3.24.</strong> ETL</a></li><li><a href="../accumulate/README.zh.html"><strong aria-hidden="true">3.25.</strong> 集合操作 &gt;&lt; Accumulate</a></li><li><a href="../acronym/README.zh.html"><strong aria-hidden="true">3.26.</strong> 术语 &gt;&lt; Acronym</a></li><li><a href="../sieve/README.zh.html"><strong aria-hidden="true">3.27.</strong> 素数筛 &gt;&lt; Sieve</a></li><li><a href="../rna-transcription/README.zh.html"><strong aria-hidden="true">3.28.</strong> RNA 转录 &gt;&lt; RNA Transcription</a></li><li><a href="../triangle/README.zh.html"><strong aria-hidden="true">3.29.</strong> 三角形</a></li><li><a href="../roman-numerals/README.zh.html"><strong aria-hidden="true">3.30.</strong> 罗马数字 &gt;&lt; Roman Numerals</a></li><li><a href="../all-your-base/README.zh.html"><strong aria-hidden="true">3.31.</strong> 你所的基本</a></li><li><a href="../grade-school/README.zh.html"><strong aria-hidden="true">3.32.</strong> 学册</a></li><li><a href="../binary-search/README.zh.html"><strong aria-hidden="true">3.33.</strong> 二分查找</a></li><li><a href="../robot-simulator/README.zh.html"><strong aria-hidden="true">3.34.</strong> 机器人模拟器</a></li><li><a href="../bracket-push/README.zh.html"><strong aria-hidden="true">3.35.</strong> 括号配套</a></li><li><a href="../luhn-from/README.zh.html"><strong aria-hidden="true">3.36.</strong> Luhn From</a></li><li><a href="../queen-attack/README.zh.html"><strong aria-hidden="true">3.37.</strong> 皇后 攻击</a></li><li><a href="../bowling/README.zh.html"><strong aria-hidden="true">3.38.</strong> 保龄球</a></li><li><a href="../sublist/README.zh.html"><strong aria-hidden="true">3.39.</strong> 子列表</a></li><li><a href="../space-age/README.zh.html"><strong aria-hidden="true">3.40.</strong> 地球年</a></li><li><a href="../luhn-trait/README.zh.html"><strong aria-hidden="true">3.41.</strong> Luhn Trait</a></li><li><a href="../macros/README.zh.html"><strong aria-hidden="true">3.42.</strong> 宏</a></li><li><a href="../allergies/README.zh.html"><strong aria-hidden="true">3.43.</strong> 过敏</a></li><li><a href="../variable-length-quantity/README.zh.html"><strong aria-hidden="true">3.44.</strong> 可变长度数量</a></li><li><a href="../phone-number/README.zh.html"><strong aria-hidden="true">3.45.</strong> 电话号码</a></li><li><a href="../wordy/README.zh.html"><strong aria-hidden="true">3.46.</strong> 罗唆</a></li><li><a href="../tournament/README.zh.html"><strong aria-hidden="true">3.47.</strong> 比赛</a></li><li><a href="../custom-set/README.zh.html"><strong aria-hidden="true">3.48.</strong> 自定义 set</a></li><li><a href="../alphametics/README.zh.html"><strong aria-hidden="true">3.49.</strong> 字母谜题</a></li><li><a href="../two-bucket/README.zh.html"><strong aria-hidden="true">3.50.</strong> 两个桶</a></li><li><a href="../pig-latin/README.zh.html"><strong aria-hidden="true">3.51.</strong> 猪的拉丁文</a></li><li><a href="../diamond/README.zh.html"><strong aria-hidden="true">3.52.</strong> 钻石</a></li><li><a href="../spiral-matrix/README.zh.html"><strong aria-hidden="true">3.53.</strong> 螺旋矩阵</a></li><li><a href="../palindrome-products/README.zh.html"><strong aria-hidden="true">3.54.</strong> 回文产品</a></li><li><a href="../poker/README.zh.html" class="active"><strong aria-hidden="true">3.55.</strong> 扑克</a></li><li><a href="../grep/README.zh.html"><strong aria-hidden="true">3.56.</strong> grep</a></li><li><a href="../scale-generator/README.zh.html"><strong aria-hidden="true">3.57.</strong> 音阶生成器</a></li><li><a href="../decimal/README.zh.html"><strong aria-hidden="true">3.58.</strong> 十进制</a></li><li><a href="../anagram/README.zh.html"><strong aria-hidden="true">3.59.</strong> 字谜</a></li><li><a href="../protein-translation/README.zh.html"><strong aria-hidden="true">3.60.</strong> 蛋白质翻译</a></li><li><a href="../robot-name/README.zh.html"><strong aria-hidden="true">3.61.</strong> 机器人名称</a></li><li><a href="../book-store/README.zh.html"><strong aria-hidden="true">3.62.</strong> 书店</a></li></ol></li><li><a href="../high.html"><strong aria-hidden="true">4.</strong> 难</a></li><li><ol class="section"><li><a href="../ocr-numbers/README.zh.html"><strong aria-hidden="true">4.1.</strong> OCR 号码</a></li><li><a href="../minesweeper/README.zh.html"><strong aria-hidden="true">4.2.</strong> 扫雷</a></li><li><a href="../dominoes/README.zh.html"><strong aria-hidden="true">4.3.</strong> 骨牌</a></li><li><a href="../parallel-letter-frequency/README.zh.html"><strong aria-hidden="true">4.4.</strong> 并行字母频率</a></li><li><a href="../rectangles/README.zh.html"><strong aria-hidden="true">4.5.</strong> 矩形</a></li><li><a href="../forth/README.zh.html"><strong aria-hidden="true">4.6.</strong> Forth</a></li><li><a href="../circular-buffer/README.zh.html"><strong aria-hidden="true">4.7.</strong> 循环缓冲区</a></li><li><a href="../react/README.zh.html"><strong aria-hidden="true">4.8.</strong> React</a></li></ol></li><li><a href="../untag.html"><strong aria-hidden="true">5.</strong> 未标签</a></li><li><ol class="section"><li><a href="../hexadecimal/README.zh.html"><strong aria-hidden="true">5.1.</strong> 十六进制</a></li><li><a href="../nucleotide-codons/README.zh.html"><strong aria-hidden="true">5.2.</strong> 核苷酸密码子</a></li><li><a href="../two-fer/README.zh.html"><strong aria-hidden="true">5.3.</strong> two-fer</a></li><li class="spacer"></li></ol></li><li><a href="../add-test-code.html">修改 mdBook 主题</a></li></ol>
    </nav>

    <div id="page-wrapper" class="page-wrapper">

        <div class="page">
            
            <div id="menu-bar" class="menu-bar">
                <div id="menu-bar-sticky-container">
                    <div class="left-buttons">
                        <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents"
                            aria-label="Toggle Table of Contents" aria-controls="sidebar">
                            <i class="fa fa-bars"></i>
                        </button>
                        <!-- START - Rust Cookbook customization -->
                        <button id="edit-button" class="icon-button" type="button" title="Fork and edit" aria-label="Fork and edit"
                            aria-haspopup="true" aria-expanded="false" aria-controls="edit">
                            <i class="fa fa-edit">Edit</i>
                        </button>
                        <!-- END - Rust Cookbook customization -->
                        <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme"
                            aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                            <i class="fa fa-paint-brush"></i>
                        </button>
                        <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
                            <li role="none"><button role="menuitem" class="theme" id="light">Light <span class="default">(default)</span></button></li>
                            <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
                        </ul>
                        
                        <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)"
                            aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
                            <i class="fa fa-search"></i>
                        </button>
                        
                    </div>

                    <h1 class="menu-title">exercisms.io 快速练习</h1>
                    
                        <div class="right-buttons">
                            <a href="../print.html" title="Print this book" aria-label="Print this book">
                                <i id="print-button" class="fa fa-print"></i>
                            </a>
                            
                        </div>
                    </div>
                </div>

            
            <div id="search-wrapper" class="hidden">
                <form id="searchbar-outer" class="searchbar-outer">
                    <input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..."
                        aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                </form>
                <div id="searchresults-outer" class="searchresults-outer hidden">
                    <div id="searchresults-header" class="searchresults-header"></div>
                    <ul id="searchresults">
                    </ul>
                </div>
            </div>
            

            <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
            <script type="text/javascript">
                document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                Array.from(document.querySelectorAll('#sidebar a')).forEach(function (link) {
                    link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                });
            </script>

            <!-- // START - Rust Cookbook customization -->
            <script>
                document.getElementById("edit-button").addEventListener("click", function () {
                    var editWindow = window.open("https://github.com/chinanf-boy/exercism-rust-zh/edit/master/src/poker/README.zh.md");
                });</script>
            <!-- // END - Rust Cookbook customization -->

            <div id="content" class="content">
                <main>
                    <a class="header" href="#poker" id="poker"><h1>Poker</h1></a>
<a class="header" href="#1-readme" id="1-readme"><h2>1. Readme</h2></a>
<a class="header" href="#扑克" id="扑克"><h1>扑克</h1></a>
<p>从扑克手牌列表中，挑选最好的手牌。</p>
<p>见<a href="https://en.wikipedia.org/wiki/List_of_poker_hands">wikipedia</a>中的扑克手牌概述.</p>
<a class="header" href="#提示" id="提示"><h2>提示</h2></a>
<ul>
<li>排名扑克手牌可以被认为是一个排序问题.</li>
<li>Rust 提供<a href="https://doc.rust-lang.org/std/vec/struct.Vec.html#method.sort">sort</a>方法，用在<code>Vec&lt;T&gt; where T: Ord</code>。</li>
<li><a href="https://doc.rust-lang.org/std/cmp/trait.Ord.html"><code>Ord</code> types</a>是一个<a href="https://en.wikipedia.org/wiki/Total_order">总顺序</a>形式，<code>a &lt; b</code>,<code>a == b</code>或<code>a &gt; b</code>其中一个一定是真的.</li>
<li>扑克手牌不符合一个总顺序：两份手牌可以不相等，但有相同的排序。例子:<code>3S 4S 5D 6H JH&quot;</code>,<code>&quot;3H 4H 5C 6C JD&quot;</code>。</li>
<li>Rust 提供<a href="https://doc.rust-lang.org/std/cmp/trait.PartialOrd.html"><code>PartialOrd</code> trait</a>处理不具有完全顺序的可排序事物的情况。然而，它没有提供标准的<code>sort</code>方法，用于<code>Vec&lt;T&gt; where T: PartialOrd</code>。在这种情况下，对向量进行排序的标准方式是<code>your_vec.sort_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::{Less|Equal|Greater}));</code>这取决于你的需要.`</li>
<li>您可以考虑实现了<code>PartialOrd</code>，表示扑克手牌的类型。</li>
</ul>
<a class="header" href="#资源" id="资源"><h2>资源</h2></a>
<p>受来自 Udacity 的培训课程的启发.<a href="https://www.udacity.com/course/viewer#!/c-cs212/">https://www.udacity.com/course/viewer#!/c-cs212/</a></p>
<a class="header" href="#2-开始你的表演" id="2-开始你的表演"><h2>2. 开始你的表演</h2></a>
<pre><pre class="playpen"><code class="language-rust editable">/// Given a list of poker hands, return a list of those hands which win.
///
/// Note the type signature: this function should return _the same_ reference to
/// the winning hand(s) as were passed in, not reconstructed strings which happen to be equal.
pub fn winning_hands&lt;'a&gt;(hands: &amp;[&amp;'a str]) -&gt; Option&lt;Vec&lt;&amp;'a str&gt;&gt; {
   unimplemented!(&quot;Out of {:?}, which hand wins?&quot;, hands)
}

</code></pre></pre>
<a class="header" href="#3-测试代码查看" id="3-测试代码查看"><h2>3. 测试代码查看</h2></a>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
// use std::collections::HashSet;

fn hs_from&lt;'a&gt;(input: &amp;[&amp;'a str]) -&gt; HashSet&lt;&amp;'a str&gt; {
   let mut hs = HashSet::new();
   for item in input.iter() {
       hs.insert(*item);
   }
   hs
}

/// Test that the expected output is produced from the given input
/// using the `winning_hands` function.
///
/// Note that the output can be in any order. Here, we use a HashSet to
/// abstract away the order of outputs.
fn test&lt;'a, 'b&gt;(input: &amp;[&amp;'a str], expected: &amp;[&amp;'b str]) {
   assert_eq!(
       hs_from(&amp;winning_hands(input).expect(&quot;This test should produce Some value&quot;,)),
       hs_from(expected)
   )
}

#[test]
fn test_single_hand_always_wins() {
   test(&amp;[&quot;4S 5S 7H 8D JC&quot;], &amp;[&quot;4S 5S 7H 8D JC&quot;])
}

#[test]
//#[ignore]
fn test_highest_card_of_all_hands_wins() {
   test(
       &amp;[&quot;4D 5S 6S 8D 3C&quot;, &quot;2S 4C 7S 9H 10H&quot;, &quot;3S 4S 5D 6H JH&quot;],
       &amp;[&quot;3S 4S 5D 6H JH&quot;],
   )
}

#[test]
//#[ignore]
fn test_a_tie_has_multiple_winners() {
   test(
       &amp;[
           &quot;4D 5S 6S 8D 3C&quot;,
           &quot;2S 4C 7S 9H 10H&quot;,
           &quot;3S 4S 5D 6H JH&quot;,
           &quot;3H 4H 5C 6C JD&quot;,
       ],
       &amp;[&quot;3S 4S 5D 6H JH&quot;, &quot;3H 4H 5C 6C JD&quot;],
   )
}

#[test]
//#[ignore]
fn test_high_card_can_be_low_card_in_an_otherwise_tie() {
   // multiple hands with the same high cards, tie compares next highest ranked,
   // down to last card
   test(&amp;[&quot;3S 5H 6S 8D 7H&quot;, &quot;2S 5D 6D 8C 7S&quot;], &amp;[&quot;3S 5H 6S 8D 7H&quot;])
}

#[test]
//#[ignore]
fn test_one_pair_beats_high_card() {
   test(&amp;[&quot;4S 5H 6C 8D KH&quot;, &quot;2S 4H 6S 4D JH&quot;], &amp;[&quot;2S 4H 6S 4D JH&quot;])
}

#[test]
//#[ignore]
fn test_highest_pair_wins() {
   test(&amp;[&quot;4S 2H 6S 2D JH&quot;, &quot;2S 4H 6C 4D JD&quot;], &amp;[&quot;2S 4H 6C 4D JD&quot;])
}

#[test]
//#[ignore]
fn test_two_pairs_beats_one_pair() {
   test(&amp;[&quot;2S 8H 6S 8D JH&quot;, &quot;4S 5H 4C 8C 5C&quot;], &amp;[&quot;4S 5H 4C 8C 5C&quot;])
}

#[test]
//#[ignore]
fn test_two_pair_ranks() {
   // both hands have two pairs, highest ranked pair wins
   test(&amp;[&quot;2S 8H 2D 8D 3H&quot;, &quot;4S 5H 4C 8S 5D&quot;], &amp;[&quot;2S 8H 2D 8D 3H&quot;])
}

#[test]
//#[ignore]
fn test_two_pairs_second_pair_cascade() {
   // both hands have two pairs, with the same highest ranked pair,
   // tie goes to low pair
   test(&amp;[&quot;2S QS 2C QD JH&quot;, &quot;JD QH JS 8D QC&quot;], &amp;[&quot;JD QH JS 8D QC&quot;])
}

#[test]
//#[ignore]
fn test_two_pairs_last_card_cascade() {
   // both hands have two identically ranked pairs,
   // tie goes to remaining card (kicker)
   test(&amp;[&quot;JD QH JS 8D QC&quot;, &quot;JS QS JC 2D QD&quot;], &amp;[&quot;JD QH JS 8D QC&quot;])
}

#[test]
//#[ignore]
fn test_three_of_a_kind_beats_two_pair() {
   test(&amp;[&quot;2S 8H 2H 8D JH&quot;, &quot;4S 5H 4C 8S 4H&quot;], &amp;[&quot;4S 5H 4C 8S 4H&quot;])
}

#[test]
//#[ignore]
fn test_three_of_a_kind_ranks() {
   //both hands have three of a kind, tie goes to highest ranked triplet
   test(&amp;[&quot;2S 2H 2C 8D JH&quot;, &quot;4S AH AS 8C AD&quot;], &amp;[&quot;4S AH AS 8C AD&quot;])
}

#[test]
//#[ignore]
fn test_three_of_a_kind_cascade_ranks() {
   // with multiple decks, two players can have same three of a kind,
   // ties go to highest remaining cards
   test(&amp;[&quot;4S AH AS 7C AD&quot;, &quot;4S AH AS 8C AD&quot;], &amp;[&quot;4S AH AS 8C AD&quot;])
}

#[test]
//#[ignore]
fn test_straight_beats_three_of_a_kind() {
   test(&amp;[&quot;4S 5H 4C 8D 4H&quot;, &quot;3S 4D 2S 6D 5C&quot;], &amp;[&quot;3S 4D 2S 6D 5C&quot;])
}

#[test]
//#[ignore]
fn test_aces_can_end_a_straight_high() {
   // aces can end a straight (10 J Q K A)
   test(&amp;[&quot;4S 5H 4C 8D 4H&quot;, &quot;10D JH QS KD AC&quot;], &amp;[&quot;10D JH QS KD AC&quot;])
}

#[test]
//#[ignore]
fn test_aces_can_end_a_straight_low() {
   // aces can start a straight (A 2 3 4 5)
   test(&amp;[&quot;4S 5H 4C 8D 4H&quot;, &quot;4D AH 3S 2D 5C&quot;], &amp;[&quot;4D AH 3S 2D 5C&quot;])
}

#[test]
//#[ignore]
fn test_straight_cascade() {
   // both hands with a straight, tie goes to highest ranked card
   test(&amp;[&quot;4S 6C 7S 8D 5H&quot;, &quot;5S 7H 8S 9D 6H&quot;], &amp;[&quot;5S 7H 8S 9D 6H&quot;])
}

#[test]
//#[ignore]
fn test_straight_scoring() {
   // even though an ace is usually high, a 5-high straight is the lowest-scoring straight
   test(&amp;[&quot;2H 3C 4D 5D 6H&quot;, &quot;4S AH 3S 2D 5H&quot;], &amp;[&quot;2H 3C 4D 5D 6H&quot;])
}

#[test]
//#[ignore]
fn test_flush_beats_a_straight() {
   test(&amp;[&quot;4C 6H 7D 8D 5H&quot;, &quot;2S 4S 5S 6S 7S&quot;], &amp;[&quot;2S 4S 5S 6S 7S&quot;])
}

#[test]
//#[ignore]
fn test_flush_cascade() {
   // both hands have a flush, tie goes to high card, down to the last one if necessary
   test(&amp;[&quot;4H 7H 8H 9H 6H&quot;, &quot;2S 4S 5S 6S 7S&quot;], &amp;[&quot;4H 7H 8H 9H 6H&quot;])
}

#[test]
//#[ignore]
fn test_full_house_beats_a_flush() {
   test(&amp;[&quot;3H 6H 7H 8H 5H&quot;, &quot;4S 5C 4C 5D 4H&quot;], &amp;[&quot;4S 5C 4C 5D 4H&quot;])
}

#[test]
//#[ignore]
fn test_full_house_ranks() {
   // both hands have a full house, tie goes to highest-ranked triplet
   test(&amp;[&quot;4H 4S 4D 9S 9D&quot;, &quot;5H 5S 5D 8S 8D&quot;], &amp;[&quot;5H 5S 5D 8S 8D&quot;])
}

#[test]
//#[ignore]
fn test_full_house_cascade() {
   // with multiple decks, both hands have a full house with the same triplet, tie goes to the pair
   test(&amp;[&quot;5H 5S 5D 9S 9D&quot;, &quot;5H 5S 5D 8S 8D&quot;], &amp;[&quot;5H 5S 5D 9S 9D&quot;])
}

#[test]
//#[ignore]
fn test_four_of_a_kind_beats_full_house() {
   test(&amp;[&quot;4S 5H 4D 5D 4H&quot;, &quot;3S 3H 2S 3D 3C&quot;], &amp;[&quot;3S 3H 2S 3D 3C&quot;])
}

#[test]
//#[ignore]
fn test_four_of_a_kind_ranks() {
   // both hands have four of a kind, tie goes to high quad
   test(&amp;[&quot;2S 2H 2C 8D 2D&quot;, &quot;4S 5H 5S 5D 5C&quot;], &amp;[&quot;4S 5H 5S 5D 5C&quot;])
}

#[test]
//#[ignore]
fn test_four_of_a_kind_cascade() {
   // with multiple decks, both hands with identical four of a kind, tie determined by kicker
   test(&amp;[&quot;3S 3H 2S 3D 3C&quot;, &quot;3S 3H 4S 3D 3C&quot;], &amp;[&quot;3S 3H 4S 3D 3C&quot;])
}

#[test]
//#[ignore]
fn test_straight_flush_beats_four_of_a_kind() {
   test(&amp;[&quot;4S 5H 5S 5D 5C&quot;, &quot;7S 8S 9S 6S 10S&quot;], &amp;[&quot;7S 8S 9S 6S 10S&quot;])
}

#[test]
//#[ignore]
fn test_straight_flush_ranks() {
   // both hands have straight flush, tie goes to highest-ranked card
   test(&amp;[&quot;4H 6H 7H 8H 5H&quot;, &quot;5S 7S 8S 9S 6S&quot;], &amp;[&quot;5S 7S 8S 9S 6S&quot;])
}

#}</code></pre></pre>
<a class="header" href="#4-答案" id="4-答案"><h2>4. 答案</h2></a>
<p><details></p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use std::cmp::Ordering;
use std::fmt;

#[macro_use]
extern crate try_opt;

extern crate counter;
use counter::Counter;

/// Given a list of poker hands, return a list of those hands which win.
///
/// Note the type signature: this function should return _the same_ reference to
/// the winning hand(s) as were passed in, not reconstructed strings which happen to be equal.
pub fn winning_hands&lt;'a&gt;(hands: &amp;[&amp;'a str]) -&gt; Option&lt;Vec&lt;&amp;'a str&gt;&gt; {
   let mut hands = try_opt!(
       hands
           .iter()
           .map(|source| Hand::try_from(source))
           .collect::&lt;Option&lt;Vec&lt;Hand&gt;&gt;&gt;()
   );
   hands.sort_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Less));
   hands.last().map(|last| {
       hands
           .iter()
           .rev()
           .take_while(|&amp;item| item.partial_cmp(last) == Some(Ordering::Equal))
           .map(|hand| hand.source)
           .collect()
   })
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Clone, Copy, Hash)]
enum Suit {
   Spades,
   Clubs,
   Diamonds,
   Hearts,
}

impl Suit {
   fn try_from(source: &amp;str) -&gt; Option&lt;Suit&gt; {
       use Suit::*;
       match source {
           &quot;S&quot; =&gt; Some(Spades),
           &quot;C&quot; =&gt; Some(Clubs),
           &quot;D&quot; =&gt; Some(Diamonds),
           &quot;H&quot; =&gt; Some(Hearts),
           _ =&gt; None,
       }
   }
}

impl fmt::Display for Suit {
   fn fmt(&amp;self, f: &amp;mut fmt::Formatter) -&gt; fmt::Result {
       use Suit::*;
       write!(
           f,
           &quot;{}&quot;,
           match *self {
               Spades =&gt; &quot;S&quot;,
               Clubs =&gt; &quot;C&quot;,
               Diamonds =&gt; &quot;D&quot;,
               Hearts =&gt; &quot;H&quot;,
           }
       )
   }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
enum Rank {
   Number(u8),
   Jack,
   Queen,
   King,
   Ace,
}

impl Rank {
   fn try_from(source: &amp;str) -&gt; Option&lt;Rank&gt; {
       use Rank::*;
       match source {
           &quot;A&quot; =&gt; Some(Ace),
           &quot;K&quot; =&gt; Some(King),
           &quot;Q&quot; =&gt; Some(Queen),
           &quot;J&quot; =&gt; Some(Jack),
           &quot;10&quot; =&gt; Some(Number(10)),
           &quot;9&quot; =&gt; Some(Number(9)),
           &quot;8&quot; =&gt; Some(Number(8)),
           &quot;7&quot; =&gt; Some(Number(7)),
           &quot;6&quot; =&gt; Some(Number(6)),
           &quot;5&quot; =&gt; Some(Number(5)),
           &quot;4&quot; =&gt; Some(Number(4)),
           &quot;3&quot; =&gt; Some(Number(3)),
           &quot;2&quot; =&gt; Some(Number(2)),
           _ =&gt; None,
       }
   }

   fn value(&amp;self) -&gt; usize {
       use Rank::*;
       match *self {
           Ace =&gt; 14,
           King =&gt; 13,
           Queen =&gt; 12,
           Jack =&gt; 11,
           Number(n) =&gt; n as usize,
       }
   }
}

impl fmt::Display for Rank {
   fn fmt(&amp;self, f: &amp;mut fmt::Formatter) -&gt; fmt::Result {
       use Rank::*;
       let num_str; // early declaration to placate NLL of Number case
       write!(
           f,
           &quot;{}&quot;,
           match *self {
               Ace =&gt; &quot;A&quot;,
               King =&gt; &quot;K&quot;,
               Queen =&gt; &quot;Q&quot;,
               Jack =&gt; &quot;J&quot;,
               Number(n) =&gt; {
                   num_str = n.to_string();
                   &amp;num_str
               }
           }
       )
   }
}

impl PartialOrd for Rank {
   fn partial_cmp(&amp;self, other: &amp;Rank) -&gt; Option&lt;Ordering&gt; {
       Some(self.value().cmp(&amp;other.value()))
   }
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Clone, Copy)]
struct Card {
   rank: Rank,
   suit: Suit,
}

impl Card {
   fn try_from_split(source: &amp;str, split: usize) -&gt; Option&lt;Card&gt; {
       Some(Card {
           rank: try_opt!(Rank::try_from(&amp;source[..split])),
           suit: try_opt!(Suit::try_from(&amp;source[split..])),
       })
   }

   fn try_from(source: &amp;str) -&gt; Option&lt;Card&gt; {
       match source.len() {
           3 =&gt; Card::try_from_split(source, 2),
           2 =&gt; Card::try_from_split(source, 1),
           _ =&gt; None,
       }
   }
}

impl fmt::Display for Card {
   fn fmt(&amp;self, f: &amp;mut fmt::Formatter) -&gt; fmt::Result {
       write!(f, &quot;{}{}&quot;, self.rank, self.suit)
   }
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
enum PokerHand {
   HighCard,
   OnePair,
   TwoPair,
   ThreeOfAKind,
   Straight,
   Flush,
   FullHouse,
   FourOfAKind,
   StraightFlush,
}

impl PokerHand {
   fn is_ace_low_straight(cards: &amp;[Card]) -&gt; bool {
       // special case: ace-low straight
       // still depends on the sorted precondition
       cards[0].rank.value() == 2 &amp;&amp; cards[4].rank == Rank::Ace
           &amp;&amp; cards
               .windows(2)
               .take(3) // (0, 1), (1, 2), (2, 3) --&gt; skips 4, ace
               .map(|pair| pair[1].rank.value() - pair[0].rank.value())
               .all(|diff| diff == 1)
   }

   fn analyze(cards: &amp;[Card]) -&gt; Option&lt;PokerHand&gt; {
       if cards.len() == 5 {
           let suit_counter = Counter::init(cards.iter().map(|c| c.suit));
           let is_flush = suit_counter
               .most_common()
               .map(|(_suit, count)| count)
               .next() == Some(5);
           // Note that `is_straight` depends on a precondition: it only works
           // if the input `cards` are sorted by rank value ascending.
           let is_straight = cards
               .windows(2)
               .map(|pair| pair[1].rank.value() - pair[0].rank.value())
               .all(|diff| diff == 1)
               || PokerHand::is_ace_low_straight(cards);

           if is_flush &amp;&amp; is_straight {
               return Some(PokerHand::StraightFlush);
           }

           let rank_counter = Counter::init(cards.iter().map(|c| c.rank));
           let mut rc_iter = rank_counter.most_common().map(|(_rank, count)| count);
           let rc_most = rc_iter.next();
           let rc_second = rc_iter.next();

           if rc_most == Some(4) {
               return Some(PokerHand::FourOfAKind);
           }
           if rc_most == Some(3) &amp;&amp; rc_second == Some(2) {
               return Some(PokerHand::FullHouse);
           }
           if is_flush {
               return Some(PokerHand::Flush);
           }
           if is_straight {
               return Some(PokerHand::Straight);
           }
           if rc_most == Some(3) {
               return Some(PokerHand::ThreeOfAKind);
           }
           if rc_most == Some(2) &amp;&amp; rc_second == Some(2) {
               return Some(PokerHand::TwoPair);
           }
           if rc_most == Some(2) {
               return Some(PokerHand::OnePair);
           }
           Some(PokerHand::HighCard)
       } else {
           None
       }
   }
}

#[derive(Debug, PartialEq, Eq)]
struct Hand&lt;'a&gt; {
   source: &amp;'a str,
   cards: [Card; 5],
   hand_type: PokerHand,
}

impl&lt;'a&gt; Hand&lt;'a&gt; {
   fn try_from(source: &amp;'a str) -&gt; Option&lt;Hand&gt; {
       let mut cards = try_opt!(
           source
               .split_whitespace()
               .map(|s| Card::try_from(s))
               .collect::&lt;Option&lt;Vec&lt;Card&gt;&gt;&gt;()
       );
       cards.sort_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Less));
       if cards.len() == 5 {
           Some(Hand {
               source: source,
               cards: [cards[0], cards[1], cards[2], cards[3], cards[4]],
               hand_type: try_opt!(PokerHand::analyze(&amp;cards)),
           })
       } else {
           None
       }
   }

   fn cmp_high_card(&amp;self, other: &amp;Hand, card: usize) -&gt; Ordering {
       let mut ordering = self.cards[card]
           .rank
           .value()
           .cmp(&amp;other.cards[card].rank.value());
       if card != 0 {
           ordering = ordering.then_with(|| self.cmp_high_card(other, card - 1));
       }
       ordering
   }

   fn value_by_frequency(&amp;self) -&gt; (Option&lt;Rank&gt;, Option&lt;Rank&gt;, Option&lt;Rank&gt;) {
       let rank_counter = Counter::init(self.cards.iter().map(|c| c.rank));
       let mut rc_iter = rank_counter
           .most_common_tiebreaker(|a, b| b.partial_cmp(a).unwrap_or(Ordering::Less))
           .map(|(rank, _count)| rank);
       (rc_iter.next(), rc_iter.next(), rc_iter.next())
   }

   fn cmp_cascade_by_freq(&amp;self, other: &amp;Hand) -&gt; Ordering {
       let (s1, s2, s3) = self.value_by_frequency();
       let (o1, o2, o3) = other.value_by_frequency();
       s1.partial_cmp(&amp;o1)
           .map(|c| {
               c.then(
                   s2.partial_cmp(&amp;o2)
                       .map(|c2| c2.then(s3.partial_cmp(&amp;o3).unwrap_or(Ordering::Equal)))
                       .unwrap_or(Ordering::Equal),
               )
           })
           .unwrap_or(Ordering::Equal)
   }

   fn cmp_straight(&amp;self, other: &amp;Hand) -&gt; Ordering {
       let s = if PokerHand::is_ace_low_straight(&amp;self.cards) {
           5
       } else {
           self.cards[4].rank.value()
       };
       let o = if PokerHand::is_ace_low_straight(&amp;other.cards) {
           5
       } else {
           other.cards[4].rank.value()
       };
       s.cmp(&amp;o)
   }
}

impl&lt;'a&gt; fmt::Display for Hand&lt;'a&gt; {
   fn fmt(&amp;self, f: &amp;mut fmt::Formatter) -&gt; fmt::Result {
       write!(f, &quot;{}&quot;, self.source)
   }
}

impl&lt;'a&gt; PartialOrd for Hand&lt;'a&gt; {
   fn partial_cmp(&amp;self, other: &amp;Hand) -&gt; Option&lt;Ordering&gt; {
       Some(self.hand_type.cmp(&amp;other.hand_type).then_with(|| {
           use PokerHand::*;
           match self.hand_type {
               HighCard =&gt; self.cmp_high_card(other, 4),
               OnePair =&gt; self.cmp_cascade_by_freq(other),
               TwoPair =&gt; self.cmp_cascade_by_freq(other),
               ThreeOfAKind =&gt; self.cmp_cascade_by_freq(other),
               Straight =&gt; self.cmp_straight(other),
               Flush =&gt; self.cmp_high_card(other, 4),
               FullHouse =&gt; self.cmp_cascade_by_freq(other),
               FourOfAKind =&gt; self.cmp_cascade_by_freq(other),
               StraightFlush =&gt; self.cmp_straight(other),
           }
       }))
   }
}

#}</code></pre></pre>
<p></details></p>
<hr />
<hr />
<a class="header" href="#填充相关" id="填充相关"><h2>填充/相关</h2></a>

                </main>

                <nav class="nav-wrapper" aria-label="Page navigation">
                    <!-- Mobile navigation buttons -->
                    
                    <a rel="prev" href="../palindrome-products/README.zh.html" class="mobile-nav-chapters previous" title="Previous chapter"
                        aria-label="Previous chapter" aria-keyshortcuts="Left">
                        <i class="fa fa-angle-left"></i>
                    </a>
                    

                    
                    <a rel="next" href="../grep/README.zh.html" class="mobile-nav-chapters next" title="Next chapter"
                        aria-label="Next chapter" aria-keyshortcuts="Right">
                        <i class="fa fa-angle-right"></i>
                    </a>
                    

                    <div style="clear: both"></div>
                </nav>
            </div>
        </div>

        <nav class="nav-wide-wrapper" aria-label="Page navigation">
            
            <a href="../palindrome-products/README.zh.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter"
                aria-keyshortcuts="Left">
                <i class="fa fa-angle-left"></i>
            </a>
            

            
            <a href="../grep/README.zh.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter"
                aria-keyshortcuts="Right">
                <i class="fa fa-angle-right"></i>
            </a>
            
        </nav>

    </div>

    

    
    <!-- Google Analytics Tag -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-128555056-1"></script>
    
    <script type="text/javascript">
        var localAddrs = ["localhost", "127.0.0.1", ""];
        if (localAddrs.indexOf(document.location.hostname) === -1) {
            window.dataLayer = window.dataLayer || [];
            function gtag() { dataLayer.push(arguments); }
            gtag('js', new Date());

            gtag('config', 'UA-128555056-1');
        }
    </script>
    

    
    <script src="../ace.js" type="text/javascript" charset="utf-8"></script>
    <script src="../editor.js" type="text/javascript" charset="utf-8"></script>
    <script src="../mode-rust.js" type="text/javascript" charset="utf-8"></script>
    <script src="../theme-dawn.js" type="text/javascript" charset="utf-8"></script>
    <script src="../theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script>
    

    
    <script src="../elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
    <script src="../mark.min.js" type="text/javascript" charset="utf-8"></script>
    <script src="../searcher.js" type="text/javascript" charset="utf-8"></script>
    

    <script src="../clipboard.min.js" type="text/javascript" charset="utf-8"></script>
    <script src="../highlight.js" type="text/javascript" charset="utf-8"></script>
    <script src="../book.js" type="text/javascript" charset="utf-8"></script>

    <!-- Custom JS scripts -->
    

    

</body>

</html>